
using UnityEngine;
using System.Collections;

public class DiceController : MonoBehaviour
{
    enum State
    {
        Animing,
        Stopped,
        Following,
        Throwing,
        Waiting
    }
    State DiceState = State.Stopped;

    //Timer
    private float fTimer = 0.0f; 
    //Posição e Rotação do Dado
    private Vector3 DicePosition; 
    private Quaternion DiceRotation;

    // Controle da Posição do Mouse
    private Vector3 mPos; 
    private Vector3 mLastPos;
    private Vector3 mDeltaPos;


    void Start()
    {
        //Pega as Posições Iniciais
        DicePosition = transform.position; 
        DiceRotation = transform.rotation;
    }

    void Update()
    {
        if (DiceState != State.Throwing)
            mDeltaPos = mPos - mLastPos;

        // Switch Para o Estado do Dado ///////////////////////////////////////////////////////////////////
        switch (DiceState)
        {
            case State.Animing:
                transform.Rotate(0, Time.deltaTime * 500.0f, 0, Space.World); //Rotação Y ao World
                if (Input.GetMouseButtonDown(0))
                    DiceState = State.Following;
                break;

            case State.Stopped:
                transform.position = DicePosition;
                transform.rotation = DiceRotation;
                break;

            case State.Following:
                transform.position = (new Vector3(mPos.x, transform.position.y, mPos.z));//transform.Translate(mDeltaPos.x, 0, mDeltaPos.z, Space.World);
                transform.Rotate(0, Time.deltaTime * 500.0f, 0, Space.World);

                if (Input.GetMouseButtonUp(0))
                {
                    if (InRect(mPos, new Vector2(18.7f, -3.5f), new Vector2(21.2f, 0.3f)))
                        DiceState = State.Throwing;
                    else
                        Restart();
                }
                break;

            case State.Throwing:
                fTimer += Time.deltaTime;

                if (NumberRange(mDeltaPos.x, 0, 0.1f) && NumberRange(mDeltaPos.z, 0, 0.1f))
                {
                    //Com uma mensagem "Don't Cheat"
                    Restart();
                    break;
                }


                transform.Rotate(mDeltaPos.z * 16.0f, 0, -mDeltaPos.x * 26.0f, Space.World);
                transform.Translate(mDeltaPos.x / (36.0f), (2.0f - fTimer) / 18.0f, mDeltaPos.z / (36.0f), Space.World);

                //Engraçado mas é assim que ativa o Rigidbody
                rigidbody.isKinematic = false; 
                break;

            case State.Waiting:
                fTimer += Time.deltaTime;
                if (GetDiceNumber() == 0)
                {
                    if (fTimer > 5.0f)
                        Restart();
                }
                break;
        }
        //////////////////////////////////////////////////////////////////////////////////////////////////////


        if (!InRect(transform.position, new Vector2(18.2f, -5.1f), new Vector2(21.7f, 4.8f)))
            Restart();
        if (Input.GetKeyDown(KeyCode.R))
            Restart();

        mLastPos = mPos;
    }

    void OnCollisionEnter(Collision Collide)
    {
        if (Collide.transform != transform.parent)
            Restart();
        if (DiceState == State.Throwing)
            DiceState = State.Waiting;
    }

    public void GiveMousePosition(Vector3 Position)
    {
        mPos = Position;
    }


    public void AnimPlay()
    {
        if (DiceState == State.Stopped)
        {
            transform.Translate(0, 0.5f, 0.1f, Space.World);
            transform.Rotate(45.0f, 0, 45.0f, Space.World);
            DiceState = State.Animing;
        }
    }

    public void AnimStop()
    {
        if (DiceState == State.Animing)
            DiceState = State.Stopped;
    }

    public void Restart()
    {
        transform.position = DicePosition;
        transform.rotation = DiceRotation;
        DiceState = State.Stopped;

        fTimer = 0.0f;
        transform.rigidbody.isKinematic = true;
    }

    public int GetDiceNumber()
    {
        if (DiceState != State.Waiting)
            return 0;
        if (!(rigidbody.IsSleeping() && rigidbody.velocity.magnitude == 0))
            return 0;

        if (NumberRange(transform.rotation.eulerAngles.x, 0, 30.0f) &&
                NumberRange(transform.rotation.eulerAngles.z, 270.0f, 30.0f))
            return 1;
        if (NumberRange(transform.rotation.eulerAngles.x, 270.0f, 30.0f) &&
                NumberRange(transform.rotation.eulerAngles.z, 0, 30.0f))
            return 2;
        if (NumberRange(transform.rotation.eulerAngles.x, 0, 30.0f) &&
                NumberRange(transform.rotation.eulerAngles.z, 180.0f, 30.0f))
            return 3;
        if (NumberRange(transform.rotation.eulerAngles.x, 90.0f, 30.0f) &&
                NumberRange(transform.rotation.eulerAngles.z, 0, 30.0f))
            return 4;
        if (NumberRange(transform.rotation.eulerAngles.x, 0, 30.0f) &&
                NumberRange(transform.rotation.eulerAngles.z, 0, 30.0f))
            return 5;
        if (NumberRange(transform.rotation.eulerAngles.x, 0, 30.0f) &&
                NumberRange(transform.rotation.eulerAngles.z, 90.0f, 30.0f))
            return 6;

        return 0;
    }


    //TOOLS
    private bool InRect(Vector3 Object, Vector3 BottomL, Vector3 TopR)
    {
        if (Object.x > BottomL.x && Object.z > BottomL.z &&
            Object.x < TopR.x && Object.z < TopR.z)
            return true;
        return false;
    }

    private bool InRect(Vector3 Object, Vector2 BottomL, Vector2 TopR)
    {
        if (Object.x > BottomL.x && Object.z > BottomL.y &&
            Object.x < TopR.x && Object.z < TopR.y)
            return true;
        return false;
    }

    //Se o Number estiver entre +-Range do CompNumber
    private bool NumberRange(float Number, float CompNumber, float Range)
    {
        if (Number > (CompNumber - Range) && Number < (CompNumber + Range))
            return true;
        return false;
    }
}